package com.qiandw.security.config;

import com.qiandw.security.entity.UserDetailImpl;
import com.qiandw.security.handle.ServerLoginSuccessHandle;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.boot.autoconfigure.security.reactive.PathRequest;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.access.AccessDeniedException;
import org.springframework.security.authentication.ReactiveAuthenticationManager;
import org.springframework.security.authentication.UserDetailsRepositoryReactiveAuthenticationManager;
import org.springframework.security.config.web.server.ServerHttpSecurity;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.userdetails.ReactiveUserDetailsService;
import org.springframework.security.core.userdetails.User;
import org.springframework.security.crypto.factory.PasswordEncoderFactories;
import org.springframework.security.web.server.SecurityWebFilterChain;
import org.springframework.security.web.server.context.WebSessionServerSecurityContextRepository;
import org.springframework.security.web.server.savedrequest.WebSessionServerRequestCache;
import reactor.core.publisher.Mono;

import java.security.Principal;
import java.util.List;
import java.util.stream.Collectors;

/**
 * @author coxx
 */
@Slf4j
@Configuration
public class ServerWebSecurityConfig {

    private final ReactiveUserDetailsService reactiveUserDetailsService;

    @Autowired
    public ServerWebSecurityConfig(@Qualifier("serverUserDetailServiceImpl") ReactiveUserDetailsService reactiveUserDetailsService) {
        this.reactiveUserDetailsService = reactiveUserDetailsService;
    }

    @Bean
    public ReactiveAuthenticationManager getManager(){
        //使用userDetails
        UserDetailsRepositoryReactiveAuthenticationManager manager = new UserDetailsRepositoryReactiveAuthenticationManager(reactiveUserDetailsService);
        manager.setPasswordEncoder(PasswordEncoderFactories.createDelegatingPasswordEncoder());
        return manager;
    }

    @Bean
    public SecurityWebFilterChain chain(ServerHttpSecurity http) throws Exception {
        return http.authorizeExchange()
                .matchers(PathRequest.toStaticResources().atCommonLocations()).permitAll()
                .pathMatchers("/login", "/error", "/logout", "/").permitAll()
                .anyExchange().authenticated()
                .and()
                .formLogin()
                .loginPage("/login")
                .authenticationSuccessHandler(new ServerLoginSuccessHandle())
                .and()
                .logout().logoutUrl("/logout")
                .and()
                .csrf().disable()
                .requestCache().requestCache(new WebSessionServerRequestCache())
                .and()
                .securityContextRepository(new WebSessionServerSecurityContextRepository())
                .build();
    }
}
